package versi.vitro.oaiserviceprovider.service.exporter.impl;

import static versi.vitro.oaiserviceprovider.helper.Constant.AND_HARVEST_OUT_MODEL_NAME;
import static versi.vitro.oaiserviceprovider.helper.Constant.XSLT_LOCATION;

import java.io.ByteArrayOutputStream;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import versi.vitro.oaiserviceprovider.application.Environment;
import versi.vitro.oaiserviceprovider.helper.GeneralHelper;
import versi.vitro.oaiserviceprovider.service.exporter.api.ExporterService;
import versi.vitro.oaiserviceprovider.service.jena.api.JenaService;
import versi.vitro.oaiserviceprovider.service.transformer.api.TransformerService;
import versi.vitro.oaiserviceprovider.service.validation.api.ValidationService;

public class ExporterServiceImplTest {

    private Mockery context;

    @BeforeMethod
    public void setUp() {
	context = new Mockery();
    }

    @Test
    public void testConstruction() {
	final String xsltFileContents = "<style></style>";
	
	final GeneralHelper generalHelper = context.mock(GeneralHelper.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(generalHelper).readResourceAsString(XSLT_LOCATION); will(returnValue(xsltFileContents));
	    }
	});

	final TransformerService transformerService = context.mock(TransformerService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final ValidationService validationService = context.mock(ValidationService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final JenaService jenaService = context.mock(JenaService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	ExporterService exporterService = new ExporterServiceImpl(generalHelper, validationService, jenaService, transformerService);

	assert xsltFileContents.equals(new String(exporterService.getXslts()));
	context.assertIsSatisfied();
    }

    @Test
    public void testRdfExtractionFromTripleStore() {

	String dummyXmlContent = "<root></root>";
	final byte[] resultByte = dummyXmlContent.getBytes();
	final ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
	{
	    public byte[] toByteArray()
	    {
		return resultByte;
	    }
	};

	final GeneralHelper generalHelper = context.mock(GeneralHelper.class);
	context.checking(new Expectations() {
	    {
		ignoring(generalHelper);
	    }
	});

	final TransformerService transformerService = context.mock(TransformerService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final ValidationService validationService = context.mock(ValidationService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final JenaService jenaService = context.mock(JenaService.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(jenaService).getModelAsOutputStream(AND_HARVEST_OUT_MODEL_NAME, "RDF/XML"); will(returnValue(outputStream));
	    }
	});

	ExporterServiceImpl exporterService = new ExporterServiceImpl(generalHelper, validationService, jenaService, transformerService);
	byte[] rdf = exporterService.extractRdfFromTripleStore();

	assert dummyXmlContent.equals(new String(rdf));
	context.assertIsSatisfied();
    }

    @Test
    public void testGenerateXmlFileWithSuccessfullValidation() {

	final String dummyXsltContent = "<style></style>";
	final byte[] xslts = dummyXsltContent.getBytes();	
	String rdfXmlContent = "<root></root>";
	final byte[] rdfBytes = rdfXmlContent.getBytes();	
	String resultXmlContent = "<result></result>";
	final byte[] resultBytes = resultXmlContent.getBytes();	

	final GeneralHelper generalHelper = context.mock(GeneralHelper.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(generalHelper).readResourceAsString(XSLT_LOCATION); will(returnValue(dummyXsltContent));
		exactly(1).of(generalHelper).writeByteArrayToLocalFile(resultBytes, Environment.OUTPUT_LOCATION);
	    }
	});

	final TransformerService transformerService = context.mock(TransformerService.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(transformerService).applyXSLT(rdfBytes, xslts); will(returnValue(resultBytes));
	    }
	});

	final ValidationService validationService = context.mock(ValidationService.class);
	context.checking(new Expectations() {
	    {
		//exactly(1).of(validationService).addSchemas(schemasLocations);
		exactly(1).of(validationService).validateAgainstSchemas(resultBytes); will(returnValue(true));
	    }
	});

	final JenaService jenaService = context.mock(JenaService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	ExporterServiceImpl exporterService = new ExporterServiceImpl(generalHelper, validationService, jenaService, transformerService) {
	    protected byte[] extractRdfFromTripleStore() {
		return rdfBytes;
	    }
	};
	exporterService.setShouldValidateAgainstSchema(true);
	
	exporterService.generateXmlFile();

	context.assertIsSatisfied();
    }


    @Test
    public void testGenerateXmlFileWithFailedValidation() {

	final String dummyXsltContent = "<style></style>";
	final byte[] xslts = dummyXsltContent.getBytes();	
	String rdfXmlContent = "<root></root>";
	final byte[] rdfBytes = rdfXmlContent.getBytes();	
	String resultXmlContent = "<result></result>";
	final byte[] resultBytes = resultXmlContent.getBytes();	

	final GeneralHelper generalHelper = context.mock(GeneralHelper.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(generalHelper).readResourceAsString(XSLT_LOCATION); will(returnValue(dummyXsltContent));
	    }
	});

	final TransformerService transformerService = context.mock(TransformerService.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(transformerService).applyXSLT(rdfBytes, xslts); will(returnValue(resultBytes));
	    }
	});

	final ValidationService validationService = context.mock(ValidationService.class);
	context.checking(new Expectations() {
	    {
		//exactly(1).of(validationService).addSchemas(schemasLocations);
		exactly(1).of(validationService).validateAgainstSchemas(resultBytes); will(returnValue(false));
	    }
	});

	final JenaService jenaService = context.mock(JenaService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	ExporterServiceImpl exporterService = new ExporterServiceImpl(generalHelper, validationService, jenaService, transformerService) {
	    protected byte[] extractRdfFromTripleStore() {
		return rdfBytes;
	    }
	};
	exporterService.setShouldValidateAgainstSchema(true);
	
	exporterService.generateXmlFile();

	context.assertIsSatisfied();
    }

    @Test
    public void testGenerateXmlFileWithoutValidation() {

	final String dummyXsltContent = "<style></style>";
	final byte[] xslts = dummyXsltContent.getBytes();	
	String rdfXmlContent = "<root></root>";
	final byte[] rdfBytes = rdfXmlContent.getBytes();	
	String resultXmlContent = "<result></result>";
	final byte[] resultBytes = resultXmlContent.getBytes();	

	final GeneralHelper generalHelper = context.mock(GeneralHelper.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(generalHelper).readResourceAsString(XSLT_LOCATION); will(returnValue(dummyXsltContent));
		exactly(1).of(generalHelper).writeByteArrayToLocalFile(resultBytes, Environment.OUTPUT_LOCATION);
	    }
	});

	final TransformerService transformerService = context.mock(TransformerService.class);
	context.checking(new Expectations() {
	    {
		exactly(1).of(transformerService).applyXSLT(rdfBytes, xslts); will(returnValue(resultBytes));
	    }
	});

	final ValidationService validationService = context.mock(ValidationService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	final JenaService jenaService = context.mock(JenaService.class);
	context.checking(new Expectations() {
	    {
	    }
	});

	ExporterServiceImpl exporterService = new ExporterServiceImpl(generalHelper, validationService, jenaService, transformerService) {
	    protected byte[] extractRdfFromTripleStore() {
		return rdfBytes;
	    }
	};

	exporterService.generateXmlFile();

	context.assertIsSatisfied();
    }
}
